<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Intervention\Image\Facades\Image;
use App\Jobs\GenerateThumbnailJob;
use Exception;

class GenerateThumbnailsCommand extends Command
{
    /**
     * The name and signature of the console command.
     */
    protected $signature = 'images:generate-thumbnails 
                            {--source=images : 源图片目录}
                            {--target=images_small : 目标缩略图目录}
                            {--size=100 : 缩略图尺寸}
                            {--queue : 使用队列异步处理}
                            {--clean : 清理目标目录后重新生成}';

    /**
     * The console command description.
     */
    protected $description = '批量生成图片缩略图';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $sourcePath = $this->option('source');
        $targetPath = $this->option('target');
        $size = (int) $this->option('size');
        $useQueue = $this->option('queue');
        $clean = $this->option('clean');

        $this->info("开始批量生成缩略图...");
        $this->info("源目录: {$sourcePath}");
        $this->info("目标目录: {$targetPath}");
        $this->info("缩略图尺寸: {$size}x{$size}");
        $this->info("使用队列: " . ($useQueue ? '是' : '否'));

        try {
            // 清理目标目录
            if ($clean) {
                $this->info("清理目标目录...");
                $this->cleanTargetDirectory($targetPath);
            }

            // 获取所有图片文件
            $imageFiles = $this->getAllImageFiles($sourcePath);
            $totalFiles = count($imageFiles);

            if ($totalFiles === 0) {
                $this->warn("没有找到需要处理的图片文件");
                return 0;
            }

            $this->info("找到 {$totalFiles} 个图片文件需要处理");

            if ($useQueue) {
                $this->processWithQueue($imageFiles, $sourcePath, $targetPath, $size);
            } else {
                $this->processDirectly($imageFiles, $sourcePath, $targetPath, $size);
            }

            $this->info("缩略图生成完成！");
            return 0;

        } catch (Exception $e) {
            $this->error("缩略图生成失败: " . $e->getMessage());
            Log::error('命令行缩略图生成失败', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine()
            ]);
            return 1;
        }
    }

    /**
     * 使用队列处理
     */
    private function processWithQueue(array $imageFiles, string $sourcePath, string $targetPath, int $size): void
    {
        $this->info("使用队列异步处理...");
        
        $progressBar = $this->output->createProgressBar(count($imageFiles));
        $progressBar->start();

        foreach ($imageFiles as $imageFile) {
            GenerateThumbnailJob::dispatch($imageFile, $sourcePath, $targetPath, $size);
            $progressBar->advance();
        }

        $progressBar->finish();
        $this->newLine();
        $this->info("已提交 " . count($imageFiles) . " 个任务到队列");
    }

    /**
     * 直接处理
     */
    private function processDirectly(array $imageFiles, string $sourcePath, string $targetPath, int $size): void
    {
        $this->info("直接处理中...");
        
        $progressBar = $this->output->createProgressBar(count($imageFiles));
        $progressBar->start();

        $processedCount = 0;
        $failedCount = 0;

        foreach ($imageFiles as $imageFile) {
            try {
                $this->generateThumbnail($imageFile, $sourcePath, $targetPath, $size);
                $processedCount++;
            } catch (Exception $e) {
                $failedCount++;
                $this->error("处理失败: {$imageFile} - " . $e->getMessage());
            }
            $progressBar->advance();
        }

        $progressBar->finish();
        $this->newLine();
        $this->info("处理完成: 成功 {$processedCount} 个，失败 {$failedCount} 个");
    }

    /**
     * 获取指定目录下的所有图片文件
     */
    private function getAllImageFiles(string $directory): array
    {
        $disk = Storage::disk('public');
        $imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
        $imageFiles = [];

        // 递归获取所有文件
        $allFiles = $disk->allFiles($directory);

        foreach ($allFiles as $file) {
            $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
            if (in_array($extension, $imageExtensions)) {
                $imageFiles[] = $file;
            }
        }

        return $imageFiles;
    }

    /**
     * 生成单个缩略图
     */
    private function generateThumbnail(string $imageFile, string $sourcePath, string $targetPath, int $size): void
    {
        $disk = Storage::disk('public');

        // 构建目标文件路径，保持目录结构
        $targetFile = str_replace($sourcePath, $targetPath, $imageFile);

        // 检查目标文件是否已存在
        if ($disk->exists($targetFile)) {
            return;
        }

        // 确保目标目录存在
        $targetDir = dirname($targetFile);
        if (!$disk->exists($targetDir)) {
            $disk->makeDirectory($targetDir, 0755, true);
        }

        // 读取原始图片
        $imagePath = $disk->path($imageFile);

        if (!file_exists($imagePath)) {
            throw new Exception("原始图片文件不存在: {$imageFile}");
        }

        // 使用 Intervention Image 生成缩略图
        $image = Image::make($imagePath);

        // 保持宽高比，生成正方形缩略图
        $image->fit($size, $size, function ($constraint) {
            $constraint->upsize();
        });

        // 保存缩略图
        $targetPath = $disk->path($targetFile);
        $image->save($targetPath, 80); // 质量设置为80%
    }

    /**
     * 清理目标目录
     */
    private function cleanTargetDirectory(string $targetPath): void
    {
        $disk = Storage::disk('public');
        
        if ($disk->exists($targetPath)) {
            $disk->deleteDirectory($targetPath);
            $this->info("目标目录已清理: {$targetPath}");
        }
    }
}
